﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using GameBoard;
using ServerIntegration;
using XMLCharSheets;

namespace CombatAutomationTheater
{
    public class RosterViewModel : INotifyPropertyChanged
    {
        public const string UnassignedTeamName = "Unassigned";
        private readonly CharacterReader _characterReader = new CharacterReader();

        private readonly Dictionary<String, ISystemConstants> _systemConstants =
            new Dictionary<string, ISystemConstants>();

        public List<Tuple<String, String>> LoadingErrors = new List<Tuple<string, string>>();
        private Func<string, IList> _activeListMethod;

        private ObservableCollection<CharacterSheet> _activeRoster = new ObservableCollection<CharacterSheet>();
        private ISystemConstants _chosenSystem;
        private ObservableCollection<String> _currentTraits = new ObservableCollection<String>();
        private ObservableCollection<String> _damageTypes = new ObservableCollection<String>();
        
        private int _rollModifier;
        private bool _ruleSetChosen;
        private CharacterSheet _selectedActiveCharacter;
        private CharacterSheet _selectedCharacter;
        private CharacterSheet _selectedFullCharacter;
        private ObservableCollection<Team> _teams = new ObservableCollection<Team>();
        private const String lineBreak = "\n-----------\n";

        public RosterViewModel()
        {
            RegisterReaders();
            RegisterConstants();
            MakeAllTeams();
            VisualsViewModel.Instance.TerrainViewModel.TerrainFactoryRegistrationChanged +=
                TerrainViewModelOnTerrainFactoryRegistrationChanged;
        }

        public ISystemConstants ChosenSystem
        {
            get { return _chosenSystem; }
        }

        public SystemService ChosenSystemService
        {
            get
            {
                if (_chosenSystem == null)
                {
                    return null;
                }
                return _chosenSystem.GetSystemService();
            }
        }

        public List<ISystemConstants> SystemConstants
        {
            get { return _systemConstants.Values.ToList(); }
        }



        public ObservableCollection<CharacterSheet> ActiveRoster
        {
            get { return _activeRoster; }
            set { _activeRoster = value; }
        }

        public ObservableCollection<Team> Teams
        {
            get { return _teams; }
            set { _teams = value; }
        }


        public ObservableCollection<String> CurrentTraits
        {
            get { return _currentTraits; }
            set { _currentTraits = value; }
        }

        public ObservableCollection<String> DamageTypes
        {
            get { return _damageTypes; }
            set { _damageTypes = value; }
        }


        public CharacterSheet SelectedFullCharacter
        {
            get { return _selectedFullCharacter; }
            set { SetActiveCharacter(value, null, null); }
        }

        public CharacterSheet SelectedActiveCharacter
        {
            get { return _selectedActiveCharacter; }
            set { SetActiveCharacter(null, value, null); }
        }

        public CharacterSheet SelectedCharacter
        {
            get { return _selectedCharacter; }
        }

        public int RollModifier
        {
            get { return _rollModifier; }
            set
            {
                _rollModifier = value;
                OnPropertyChanged("RollModifier");
            }
        }

     
        public BoardsViewModel.BoardTypes ZoomTargetBoardType
        {
            get
            {
                if (MainConfigurationSettingsViewModel.Instance.OrientAllCamerasToMatchMain)
                {
                    return BoardsViewModel.BoardTypes.All;
                }
                return BoardsViewModel.BoardTypes.Main;
            }
        }

        public Team UnassignedTeam {get { return Teams.FirstOrDefault(x => x.TeamName == UnassignedTeamName); }}

        public int CurrentRound { get; set; }

        private void TerrainViewModelOnTerrainFactoryRegistrationChanged
            (object sender, TerrainFactoryRegistrationChangedEventArgs terrainFactoryRegistrationChangedEventArgs)
        {
            if (ChosenSystemService != null)
            {
                ChosenSystemService.OnTerrainFactoryRegisteredChanged(terrainFactoryRegistrationChangedEventArgs);
            }
        }

        private void RegisterReaders()
        {
            var nwodReader = new NWoDCharacterReader();
            _characterReader.RegisterReader(NWoDConstants.SystemID, nwodReader);
            _characterReader.RegisterReader(PathfinderConstants.SystemID, new PathfinderCharacterReader());
            _characterReader.RegisterWebReader(NWoDConstants.SystemID, nwodReader);
        }

        private void RegisterConstants()
        {
            _systemConstants.Add(NWoDConstants.SystemID, new NWoDConstants());
            _systemConstants.Add(PathfinderConstants.SystemID, new PathfinderConstants());
        }

        internal void MakeAllTeams()
        {
            if (!Teams.Any(x => x.TeamName.Equals("Team 1")))
                Teams.Add(new Team("Team 1", Colors.Red));
            if (!Teams.Any(x => x.TeamName.Equals("Team 2")))
                Teams.Add(new Team("Team 2", Colors.Blue));
            if (!Teams.Any(x => x.TeamName.Equals("Team 3")))
                Teams.Add(new Team("Team 3", Colors.White));
            if (!Teams.Any(x => x.TeamName.Equals("Team 4")))
                Teams.Add(new Team("Team 4", Colors.Black));

            if (!Teams.Any(x => x.TeamName.Equals("Team 5")))
                Teams.Add(new Team("Team 5", Colors.Green));
            if (!Teams.Any(x => x.TeamName.Equals("Team 6")))
                Teams.Add(new Team("Team 6", Colors.Yellow));
            if (!Teams.Any(x => x.TeamName.Equals("Team 7")))
                Teams.Add(new Team("Team 7", Colors.Teal));
            if (!Teams.Any(x => x.TeamName.Equals("Team 8")))
                Teams.Add(new Team("Team 8", Colors.Purple));
            if (!Teams.Any(x => x.TeamName.Equals(UnassignedTeamName)))
                Teams.Add(new Team(UnassignedTeamName, Colors.Beige));
        }

        private void SetActiveCharacter(CharacterSheet fullChar, CharacterSheet activeChar,
                                        CharacterSheet deceasedCharacter)
        {
            if (activeChar != null)
            {
                _selectedCharacter = activeChar;
            }
            else if (fullChar != null)
            {
                _selectedCharacter = fullChar;
            }
            else if (deceasedCharacter != null)
            {
                _selectedCharacter = deceasedCharacter;
            }
            else
            {
                _selectedCharacter = null;
            }
            _selectedActiveCharacter = activeChar;
            _selectedFullCharacter = fullChar;
            OnPropertyChanged("SelectedFullCharacter");
            OnPropertyChanged("SelectedActiveCharacter");
            OnPropertyChanged("SelectedCharacter");
            if (ChosenSystemService != null)
            {
                ChosenSystemService.ActiveCharacterChanged();
            }
        }


        internal void PopulateCharacters(String sourceDir)
        {
            // Process the list of files found in the directory. 
            string[] fileEntries = Directory.GetFiles(sourceDir);
            foreach (string fileName in fileEntries)
            {
                if (!Path.GetExtension(fileName).ToLower().Equals(".xml"))
                {
                    continue;
                }
                CharacterSheet readCharacter = ReadCharacterFromFile(fileName);
                if (readCharacter != null)
                {
                    CharacterSheets.RegisterSheet(readCharacter);
                }
                else
                {
                    MessageBox.Show("Error reading " + fileName);
                }
            }

            // Recurse into subdirectories of this directory.
            string[] subdirEntries = Directory.GetDirectories(sourceDir);
            foreach (string subdir in subdirEntries)
            {
                PopulateCharacters(subdir);
            }
        }

        public CharacterSheet ReadCharacterFromFile(String fileName)
        {
            return _characterReader.Read(fileName);
        }

        internal void RollCharacters(IList characters, IList selectedTraits)
        {
            TextReporter.Report(lineBreak);
            foreach (object curItem in characters)
            {
                var curChar = curItem as CharacterSheet;
                var involvedTraits = new List<string>();
                foreach (object cur in selectedTraits)
                {
                    involvedTraits.Add(cur.ToString());
                }
                if (CanRoll(curChar, involvedTraits))
                {
                    RollCharacter(curChar, involvedTraits);
                    TextReporter.Report("\n");
                }
            }
        }

        private bool CanRoll(CharacterSheet involvedCharacter, List<string> involvedTraits)
        {
            bool canRoll = true;
            var missingTraits = new List<String>();
            var charTraits = new List<Trait>();
            foreach (string curTrait in involvedTraits)
            {
                bool hasTrait = involvedCharacter.HasTrait(curTrait);
                if (!hasTrait)
                {
                    missingTraits.Add(curTrait);
                }
                else
                {
                    charTraits.Add(involvedCharacter.FindNumericTrait(curTrait));
                }
                canRoll &= hasTrait;
            }
            if (!canRoll)
            {
                var result = new StringBuilder();
                result.Append(involvedCharacter.Name + " was missing traits:");
                for (int curIndex = 0; curIndex < missingTraits.Count(); curIndex++)
                {
                    if (curIndex == missingTraits.Count() - 1)
                    {
                        result.Append(" " + missingTraits[curIndex]);
                    }
                    else
                    {
                        result.Append(", " + missingTraits[curIndex]);
                    }
                }
                TextReporter.Report("\n" + result + "\n");
            }
            return canRoll;
        }

        private void RollCharacter(CharacterSheet involvedCharacter, List<string> involvedTraits)
        {
            String allTraits = "";
            for (int curIndex = 0; curIndex < involvedTraits.Count; curIndex++)
            {
                allTraits = allTraits + involvedTraits[curIndex];
                if (curIndex != involvedTraits.Count - 1)
                {
                    allTraits = allTraits + ", ";
                }
            }

            TextReporter.Report(involvedCharacter.Name + " rolled (" + allTraits + " ");
            int totalDice = 0;
            var charTraits = new List<Trait>();
            foreach (string cur in involvedTraits)
            {
                NumericIntTrait numericTrait = involvedCharacter.FindNumericTrait(cur);
                totalDice += numericTrait.TraitValue;
                charTraits.Add(numericTrait);
            }
            TextReporter.Report(totalDice + " pool)");
            String result =
                involvedCharacter.RollBasePool(charTraits,
                                               RollModifier + involvedCharacter.StatusEffectBasedRollModifier)
                                 .ResultDescription;
            TextReporter.Report(": " + result);
        }

        internal void DoDamage(IList characters, int value, String damageType)
        {
            foreach (object curItem in characters)
            {
                var curChar = curItem as CharacterSheet;
                curChar.DoDamage(value, damageType);
                TextReporter.Report("\n" + curChar.Name + " took ");
                TextReporter.Report(value + " ", TextReporter.DamageBrush);
                TextReporter.Report(damageType + "\n" + curChar.Name + ": " + curChar.HealthStatusLineDescription);
            }
        }


        internal void ResetHealth(IList characters)
        {
            foreach (object curItem in characters)
            {
                var curChar = curItem as CharacterSheet;
                curChar.ResetHealth();
                TextReporter.Report("Restored full health to " + curChar.Name + "\n");
            }
        }


        public void RemoveStatusEffects(IList characters)
        {
            foreach (object curItem in characters)
            {
                var curChar = curItem as CharacterSheet;
                if (curChar.StatusEffects.Any())
                {
                    TextReporter.Report("Removed status effects from " + curChar.Name + ".\n");
                }
                else
                {
                    TextReporter.Report(curChar.Name + " had no status effects to remove.\n");
                }
                curChar.StatusEffects.Clear();
                curChar.NotifyStatusChange();
                if (curChar.HasVisual)
                {
                    List<StatusEffectDisplay> statuses = MakeStatusList(curChar.StatusEffects);
                    VisualsViewModel.Instance.RemakeInfoTextFor(curChar.UniqueCharacterID, statuses);
                }
            }
        }

        internal void RollInitiative()
        {
            if (MainConfigurationSettingsViewModel.Instance.RerollInitiativeEachRound)
            {
                foreach (CharacterSheet curChar in ActiveRoster)
                {
                    curChar.RollInitiative();
                }
            }
            else
            {
                var toRoll = ActiveRoster.Where(x => x.CurInitiative == -1);
                foreach (CharacterSheet curChar in toRoll)
                {
                    curChar.RollInitiative();
                }
            }
            List<CharacterSheet> q = ActiveRoster.OrderByDescending(x => x.CurInitiative).ToList();
            ActiveRoster.Clear();
            foreach (CharacterSheet curChar in q)
            {
                ActiveRoster.Add(curChar);
            }
        }

        internal void RemoveCharactersFromRosters(IList characters)
        {
            for (int curIndex = characters.Count - 1; curIndex >= 0; curIndex--)
            {
                var curChar = characters[curIndex] as CharacterSheet;
                if (ActiveRoster.Contains(curChar))
                {
                    ActiveRoster.Remove(curChar);
                    SelectedActiveCharacter = null;
                }
                foreach (Team cur in Teams)
                {
                    if (cur.TeamMembers.Contains(curChar))
                        cur.TeamMembers.Remove(curChar);
                }
                foreach (CharacterSheet cur in ActiveRoster)
                {
                    if (cur.Target == curChar)
                    {
                        cur.Target = null;
                    }
                }
                if (curChar.HasVisual)
                {
                    VisualsViewModel.Instance.RemovePiece(curChar.UniqueCharacterID);
                }
                if (ChosenSystemService != null)
                {
                    ChosenSystemService.PieceRemoved(curChar);
                }
            }
        }

        internal void PerformAutomaticActions(IList actors)
        {
            var activeActors = new List<CharacterSheet>();
            foreach (object curItem in actors)
            {
                var curChar = curItem as CharacterSheet;
                activeActors.Add(curChar);
            }
            activeActors = activeActors.OrderByDescending(x => x.CurInitiative).ToList();
            foreach (CharacterSheet cur in activeActors)
            {
                cur.PerformAutomaticActions();
            }
        }

        internal void RollAttackTarget(IList attackers)
        {
            TextReporter.Report(lineBreak);
            var targetToDamage = new Dictionary<CharacterSheet, List<Damage>>();
            foreach (object curItem in attackers)
            {
                var curChar = curItem as CharacterSheet;
                var attackName = new List<String>();
                if (curChar.Target == null)
                {
                    TextReporter.Report(curChar.Name + " has no target.\n");
                    continue;
                }
                curChar.HasAttacked = true;
                attackName.Add(curChar.ChosenAttack);
                if (CanRoll(curChar, attackName))
                {
                    TextReporter.Report(curChar.Name + " rolled attack {" + curChar.ChosenAttackValue + " - "
                                        + curChar.ChosenAttackString + "} on " + curChar.Target.Name + "\n");

                    List<Damage> damageResult = curChar.AttackTarget(RollModifier);
                    if (!targetToDamage.ContainsKey(curChar.Target))
                    {
                        targetToDamage.Add(curChar.Target, new List<Damage>());
                    }
                    if (curChar is NWoDCharacter)
                    {
                        TextReporter.Report("\nFinal pool: " + curChar.FinalAttackPool);
                    }
                    targetToDamage[curChar.Target].AddRange(damageResult);
                    TextReporter.Report("\n" + curChar.RollResults + "\n");
                }
                Guid curTargetID = curChar.Target.UniqueCharacterID;
                if (curChar.HasVisual && curChar.Target.HasVisual)
                {
                    VisualsViewModel.Instance.DrawAttack(curChar.UniqueCharacterID,
                                                         curTargetID, curChar.Team.TeamColor,
                                                         new Duration(new TimeSpan(0, 0, 0, 5)));
                }
            }

            SummarizeDamage(targetToDamage);
        }


        private void SummarizeDamage(Dictionary<CharacterSheet, List<Damage>> targetToDamage)
        {
            if (!targetToDamage.Any(x => x.Value.Any()))
            {
                TextReporter.Report("No damage dealt by attackers.\n");
                return;
            }
            TextReporter.Report("\n\nDamage summary:");
            foreach (var curTargetPair in targetToDamage)
            {
                var damageResultsTotal = new Dictionary<string, int>();
                int summedDamage = 0;
                foreach (Damage cur in curTargetPair.Value)
                {
                    if (!damageResultsTotal.ContainsKey(cur.DamageDescriptor))
                    {
                        damageResultsTotal.Add(cur.DamageDescriptor, 0);
                    }
                    damageResultsTotal[cur.DamageDescriptor] += cur.DamageValue;
                    if (cur.CanBeSummed())
                    {
                        summedDamage += cur.DamageValue;
                    }
                }
                TextReporter.Report("\n\t" + curTargetPair.Key.Name + " took ");
                if (summedDamage > 0)
                {
                    TextReporter.Report(summedDamage + " total (");
                }
                foreach (var curDamage in damageResultsTotal)
                {
                    TextReporter.Report(curDamage.Key + " " + curDamage.Value + " ", TextReporter.DamageBrush);
                }
                if (summedDamage > 0)
                {
                    TextReporter.Report(")");
                }
                TextReporter.Report("\t Current Status: " + curTargetPair.Key.HealthStatusLineDescription);
            }
        }


        internal void NewRound()
        {
            if (MainConfigurationSettingsViewModel.Instance.AutoSaveEachTurn)
            {
                FileSaveOpenService.AutoSave("R_" + CurrentRound);
            }
            foreach (CharacterSheet curCharacter in ActiveRoster)
            {
                curCharacter.NewRound();
            }
        }

        internal void RecalculateCombatStats(IList characters)
        {
            foreach (object curItem in characters)
            {
                var curChar = curItem as CharacterSheet;
                curChar.PopulateCombatTraits();
            }
        }

        internal void SetTargets(List<CharacterSheet> attackers,
                                 List<String> otherAttacks,
                                 CharacterSheet target,
                                 string attackType,
                                 string damageType)
        {
            foreach (CharacterSheet curChar in attackers)
            {
                curChar.SetTarget(target, otherAttacks, attackType, damageType);
            }
        }


        internal void AssignStatus(IList characters, int duration, string description, int modifier)
        {
            foreach (object curItem in characters)
            {
                var curCharacter = curItem as CharacterSheet;
                curCharacter.AssignStatus(description, duration, modifier);
                if (curCharacter.HasVisual)
                {
                    List<StatusEffectDisplay> statusList = MakeStatusList(curCharacter.StatusEffects);
                    VisualsViewModel.Instance.RemakeInfoTextFor(curCharacter.UniqueCharacterID, statusList);
                }
            }
        }

        internal void MarkCharactersAsDeceased()
        {
            List<CharacterSheet> activeRosterList = ActiveRoster.ToList();
            for (int curIndex = activeRosterList.Count() - 1; curIndex >= 0; curIndex--)
            {
                if (activeRosterList[curIndex].IsIncapacitated)
                {
                    //The character should be removed from the active list first.
                    //Otherwise, when removed later, it would trigger a 'set inactive'
                    //event, which cannot complete due to the character already being
                    //removed from all the boards.
                    ActiveRoster.Remove(activeRosterList[curIndex]);
                    if (activeRosterList[curIndex].HasVisual)
                    {
                        Guid curId = activeRosterList[curIndex].UniqueCharacterID;
                        VisualsViewModel.Instance.RemovePiece(curId);
                    }
                    foreach (CharacterSheet cur in activeRosterList.Where(x => x.Target == activeRosterList[curIndex]))
                    {
                        cur.Target = null;
                    }
                }
            }
        }

        internal void ResetToActive(IList activeObjects, IList inactiveObjects)
        {
            foreach (CharacterSheet cur in inactiveObjects)
            {
                CharacterSheet curCharacter = cur;
                if (curCharacter.HasVisual)
                {
                    VisualsViewModel.Instance.SetInactive(curCharacter.UniqueCharacterID);
                }
            }
            AddToActive(activeObjects);
        }

        internal void AddToActive(IList selectedObjects)
        {
            List<CharacterSheet> selectedCharacters = GetListOfCharacters(selectedObjects);
            foreach (CharacterSheet curCharacter in selectedCharacters)
            {
                if (curCharacter.HasVisual)
                {
                    VisualsViewModel.Instance.SetActive(
                        curCharacter.UniqueCharacterID);
                }
            }
            VisualsViewModel.Instance.DrawGroupMovementCircleIfNeeded();
        }

        private List<CharacterSheet> GetListOfCharacters(IList selectedObjects)
        {
            var values = new List<CharacterSheet>();
            foreach (object cur in selectedObjects)
            {
                values.Add(cur as CharacterSheet);
            }
            return values;
        }

        internal void AddVisualToCharacters(IList characters, PictureFileInfo pictureInfo, Team chosenTeam)
        {
            foreach (object curItem in characters)
            {
                var curCharacter = curItem as CharacterSheet;
                if (curCharacter.Team != null)
                {
                    curCharacter.Team.TeamMembers.Remove(curCharacter);
                    curCharacter.Team = null;
                }
                RegisterTeamMemberOnTeam(curCharacter, chosenTeam);

                var baseOrigin = new Point3D(0, 0, 0);
                if (curCharacter.HasVisual)
                {
                    baseOrigin = curCharacter.FirstVisual.Location;
                    VisualsViewModel.Instance.RemovePiece(curCharacter.UniqueCharacterID);
                }
                VisualsViewModel.Instance.AddImagePieceToMap
                    (pictureInfo.PictureFile, chosenTeam.TeamColor, curCharacter.Name,
                     curCharacter.HeightTrait.TraitValue, baseOrigin, MakeStatusList(curCharacter.StatusEffects),
                     curCharacter.SpeedTrait.TraitValue, curCharacter.UniqueCharacterID,
                     _chosenSystem.GetMovementCircleRadiusList()
                    );
            }
        }


        internal void RegisterTeamMemberOnTeam(CharacterSheet curCharacter, Team chosenTeam)
        {
            curCharacter.Team = chosenTeam;
            chosenTeam.TeamMembers.Add(curCharacter);
        }

        internal List<StatusEffectDisplay> MakeStatusList(List<StatusEffect> list)
        {
            var description = new List<StatusEffectDisplay>();
            foreach (StatusEffect cur in list)
            {
                description.Add(cur.CreateStatusEffectDisplay());
            }
            return description;
        }


        internal void SetRulesetMode(string rulesetName)
        {
                

        }

        internal UIElement GetCombatControl()
        {
            return _chosenSystem.GetSystemService().CustomControlItem();
        }

        internal UIElement GetVisualControl()
        {
            if (_chosenSystem.GetSystemService().CustomVisualControlItem() != null)
            {
                return _chosenSystem.GetSystemService().CustomVisualControlItem();
            }
            return null;
        }

        internal void RegisterNewCharacter(CharacterSheet newInstance)
        {
            ActiveRoster.Add(newInstance);
            if (!_ruleSetChosen)
            {
                SetRulesetMode(newInstance.Ruleset);
                _chosenSystem = _systemConstants[newInstance.Ruleset];
                CharacterSheets.SetActiveSystemTo(_systemConstants[newInstance.Ruleset]);
                OnRulesetSelected(new RulesetSelectedEventArgs(newInstance.Ruleset));
                _ruleSetChosen = true;
            }
        }

      
        public event EventHandler<RulesetSelectedEventArgs> RulesetSelected;

        protected virtual void OnRulesetSelected(RulesetSelectedEventArgs e)
        {
            EventHandler<RulesetSelectedEventArgs> handler = RulesetSelected;
            if (handler != null)
            {
                handler(this, e);
            }
        }


        internal void ReportText(ReportTextEventArgs reportTextEventArgs)
        {
            OnReportTextEvent(reportTextEventArgs);
        }

        public event EventHandler ReportTextEvent;

        private void OnReportTextEvent(ReportTextEventArgs e)
        {
            EventHandler handler = ReportTextEvent;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public event EventHandler ClearReportTextEvent;

        private void OnClearReportTextEvent(EventArgs e)
        {
            EventHandler handler = ClearReportTextEvent;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        internal void PathfinderSingleAttack(IList attackers)
        {
            foreach (object cur in attackers)
            {
                var curChar = cur as PathfinderCharacter;
                if (curChar != null)
                {
                    curChar.SingleAttackOnly = true;
                }
            }
            RollAttackTarget(attackers);
            foreach (object cur in attackers)
            {
                var curChar = cur as PathfinderCharacter;
                if (curChar != null)
                {
                    curChar.SingleAttackOnly = false;
                }
            }
        }

        internal void OpenActiveRoster(IList<CharacterSheet> newRoster)
        {
            var oldRoster = new List<CharacterSheet>();
            oldRoster.AddRange(ActiveRoster);
            RemoveCharactersFromRosters(oldRoster);
            foreach (CharacterSheet curNew in newRoster)
            {
                RegisterNewCharacter(curNew);
            }
            foreach (CharacterSheet cur in newRoster)
            {
                VisualsViewModel.Instance.RemakeInfoTextFor(cur.UniqueCharacterID, MakeStatusList(cur.StatusEffects));
            }
        }

        internal void OpenTeams(IList<Team> newteams)
        {
            foreach (Team curNew in newteams)
            {
                Teams.Add(curNew);
            }
        }

        internal void ClearResultText()
        {
            OnClearReportTextEvent(null);
        }

        internal void LoadDamageFor(string rulesetName)
        {
            List<string> types = _characterReader.LoadDamageFor(rulesetName);
            foreach (string cur in types)
            {
                DamageTypes.Add(cur);
            }
        }

        internal void ShowErrors()
        {
            if (LoadingErrors.Any())
            {
                var lew = new LoadingErrorsWindow();
                lew.SetErrors(LoadingErrors);
                lew.ShowDialog();
            }
        }


        public void StoreGetActiveList(Func<string, IList> myMethodName)
        {
            _activeListMethod = myMethodName;
        }

        public IList GetActiveList()
        {
            return _activeListMethod("");
        }

        internal void ResetOnOpen()
        {
            ActiveRoster.Clear();
            Teams.Clear();
            _ruleSetChosen = false;
            OnRulesetSelected(new RulesetSelectedEventArgs(RulesetSelectedEventArgs.ClearRulesetString));
        }

        internal void ServerCharacterReceived(object sender, EventArgs e)
        {
            if (_chosenSystem == null)
            {
                _chosenSystem = new NWoDConstants();
            }
            if (!(_chosenSystem is NWoDConstants))
            {
                MessageBox.Show("Error", "This system does not support NWoD characters", MessageBoxButton.OK,
                                MessageBoxImage.Error);
            }
            var webCharacterEvent = e as WebCharacterCreatedEventArgs;
            if (webCharacterEvent != null)
            {
                try
                {
                    if (
                        !String.IsNullOrWhiteSpace(_chosenSystem.SystemIDProperty) &&
                        !webCharacterEvent.TransferCharacter.SystemLabel.Equals(_chosenSystem.SystemIDProperty))
                    {
                        throw new Exception("Could not load this character - ruleset does not match active ruleset " +
                                            _chosenSystem.SystemIDProperty);
                    }
                    CharacterSheet readCharacter = _characterReader.ReadWebCharacter(webCharacterEvent.TransferCharacter);
                    if (readCharacter != null)
                    {
                        CharacterSheets.RegisterSheet(readCharacter);
                        PictureSelectionViewModel.Instance.AddImage(
                            webCharacterEvent.TransferCharacter.CharacterImageLocation);
                    }
                }
                catch (Exception exception)
                {
                    LoadingErrors.Add(new Tuple<String, String>("Web character", exception.Message));
                    ShowErrors();
                    LoadingErrors.Clear();
                }
            }
        }

        internal void ResetVisualData(Guid UniqueCharacterID, string Name, NumericIntTrait SpeedTrait,
                                      NumericIntTrait HeightTrait)
        {
            VisualsViewModel.Instance.ResetVisualDataFor(
                UniqueCharacterID, Name, SpeedTrait.TraitValue, HeightTrait.TraitValue
                );
        }


        public void OpenSystemData(SystemSaveData systemSavedData)
        {
            if (ChosenSystemService != null)
                ChosenSystemService.OpenSavedData(systemSavedData);
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        #endregion
    }
}